﻿using System;
using System.Linq;
using System.Configuration;
using Ue.CQRS.Bus;
using Ue.CQRS.Configuration;
using Ue.CQRS.DistributionManager;
using Ue.CQRS.Ioc;

namespace Ue.CQRS
{
    public sealed class AppContext : IContainer
    {
        #region 构造及字段

        private IContainer container;

        public AppContext(IContainer container)
            : this(container, ConfigurationManager.AppSettings["ue_cqrs_settigs_path"]) { }

        public AppContext(IContainer container, string configPath)
            : this(container, ConfigurationFactory.Build(configPath)) { }

        public AppContext(IContainer container, IConfiguration configuration)
        {
            if (configuration == null)
            {
                throw new ArgumentNullException("configuration");
            }

            this.container = new DefaultContainer(configuration,container);
        }

        #endregion

        public bool IsStart { get; private set; }

        public void Start()
        {
            this.IsStart = true;
            AppContext.currentContext = this;
        }

        public void Stop()
        {
            this.IsStart = false;
            AppContext.currentContext = null;
        }

        #region IContainer

        public T Resolve<T>() where T : class
        {
            return this.container.Resolve<T>();
        }

        public bool IsRegistered(Type type)
        {
            return this.container.IsRegistered(type);
        }

        #endregion

        #region private methods

        private IBus BuildBus()
        {
            return null;
        }

        /// <summary>
        /// 注册事件处理器
        /// </summary>
        private void RegisterHandle()
        {
            var distributor = this.Resolve<IDistributor>();
            if (distributor != null)
            {
                var assemblys = AppDomain.CurrentDomain
                    .GetAssemblies()
                    .Where(item => !item.IsDynamic && item.CodeBase.IndexOf("Microsoft") == -1)
                    .ToArray();

                foreach (var asselbly in assemblys)
                {
                    distributor.Register(asselbly);
                }
            }
        }

        #endregion

        #region static field and method

        public static AppContext currentContext;

        public static AppContext GetContext()
        {
            if (AppContext.currentContext == null)
            {
                throw new DomainException("未启用AppContext");
            }

            return AppContext.currentContext;
        }

        #region Execution

        public static void ExecutionByContext(Action<AppContext> action)
        {
            var context = AppContext.GetContext();
            if (context != null)
            {
                action(context);
            }
        }

        public static void ExecutionByBus(Action<IBus> action)
        {
            AppContext.ExecutionByContext(context =>
            {
                var bus = GetContext().Resolve<IBus>();
                if (bus != null)
                {
                    action(bus);
                }
            });
        }

        #endregion

        #endregion
    }
}
